iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0

JavaScript 是採用語法作用域,也叫做靜態作用域,意思是在語法解析的時候就已經確定作用域。相對地,動態作用域是在函式調用的時候才會決定它的作用域,但此處以 JavaScript 為主,先不多介紹動態作用域。

先撰寫一個簡單的函式來做範例:

function callName() {
    let Jack = "傑克";
    console.log(Jack); //傑克
}

callName();

上面的函式裡面我們在定義變數後方直接使用 console.log 試著把 Jack 印出來,在執行函式後就會執行該段程式碼,並把值給印出來得到 傑克

接下來讓我們把裡面的 console.log 拿到外面來試著印印看:

function callName() {
    let Jack = "傑克";
}

callName();
console.log(Jack); // Jack is not defined

此時會得到 Jack is not defined 並沒有被定義的結果

為什麼呢?

原因是因為 JavaScript 的作用域是在這個函式裡面,所以當我們在函式裡面宣告一個變數的時候,外層是讀不到該變數的。

全域

JavaScript 的作用域是一層一層向內的,外層會有一個全域的作用域,內層則是被 function 所包著

以下圖為例,這裡有兩個不同的函式,這兩個函式的作用域就是獨立的,而在外層還有一個全域的作用域包著這兩個函式。

如果在某個作用域內需要特定變數,但在該作用域內沒有該變數的時候,就會向外查找,意思是往外面的作用域去找有沒有該變數可以使用,如果外面有該變數可以使用就會直接拿來使用。但如果外面也找不到該變數的話,就會顯示變數沒有被定義的錯誤。


此處再以一段程式碼為例:

let value = 1;

function fn1(){
    console.log(value); // 語法(靜態)作用域:1
    // 動態作用域:2
}

function fn2(){
    let value = 2;
    fn1();
}

fn2();

雖然在第二個函式內部重新賦予了 value 的值,但因為作用域如同前面所說,靜態作用域在語法解析的時候就已經確定作用域,所以我們在寫 function 的時候,作用域就已經確定了,並不會在執行過程中再次改變作用域。

所以在 fn1 執行時不會受到 fn2 的影響,且在內部找不到 value 這個變數,於是就會向外查找並印出該值。

如果是動態作用域的語法,則會在調用該函式時才會決定作用域,所以此處 fn1 執行時會向外查找到 fn2 內的變數 value 並印出該值。


參考資料

線上課程


上一篇
Day28 箭頭函式 Arrow function
下一篇
Day30 Hoisting 提升
系列文
從基礎開始,用 JavaScript 從頭建立起程式肌肉 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言